<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    
  </style>
</head>
<body>
  <div class="box">
    <h1> {{ msg }} </h1>
    <p> my name is {{name}} </p>
    <p> 我的年龄是{{age}} </p>
    <p> 我的性别是{{sex}} </p>
    <p> 我的性别是{{sex}} </p>
    <p> 我的性别是{{sex}} </p>
    <p> my name is {{name}} </p>
    <p> 我的年龄是{{   age   }} </p>
    <p> my name is {{name}} </p>
    <p> 我的年龄是{{age}} </p>
    <p> my name is {{name}} </p>
    <p> 我的年龄是{{age}} </p>
  </div>
  
  姓名：<input type="text" class="txt1">
  年龄：<input type="text" class="txt2">
  性别：<input type="text" class="txt3">
  
  <div class="box2">
    {{ hello world }}
  </div>
</body>
<script>
  // const data = {
  //   msg:"数据绑定",
  //   name:"admin",
  //   age:18
  // }
  // document.querySelector(".txt").oninput = function(){
  //   data.name = this.value;
  // }

  // 启动后，返回值为劫持后的对象
  const p = myVue({
    el:".box",
    data: {
      msg:"数据绑定",
      name:"admin",
      age:18,
      sex:"男"
    }
  })


  function myVue( { el, data } ){
    // 根据传入的选择器，决定数据影响的视图结构
    const ele = document.querySelector(el);
    // 提前将要修改的视图结构内容保存起来
    const str = ele.innerHTML;
    // 初始情况下，根据数据渲染视图
    render(str);

    function render(str){
      // 编写正则，准备查找所有数据标志：{{ 数据名 }}
      const reg = /{{\s*[a-z_$][\w$]*\s*}}/g;
      // 解析每个需要替换的数据标志
      str.match(reg).forEach(val=>{
        // 从数据标志中，获取数据名（属性名）
        const r = /[a-z_$][\w$]*/;
        // 根据数据标志，替换成对应的属性
        str = str.replace(val, data[val.match(r)[0]]);
      })
      // 将替换完成后的视图内容，放回原结构
      ele.innerHTML = str;
    }
    // 数据劫持
    return new Proxy(data, {
      get(){},
      set(origin, attr, val){
        // 改变数据
        origin[attr] = val;
        // 当数据被改变后，重新根据数据渲染视图
        render(str);
      }
    })
  }


  // 测试，当劫持后的数据发生改变时，是否会影响视图
  document.querySelector(".txt1").oninput = function(){
    p.name = this.value;
  }
  document.querySelector(".txt2").oninput = function(){
    p.age = this.value;
  }
  document.querySelector(".txt3").oninput = function(){
    p.sex = this.value;
  }


</script>
</html>